using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace gears
{
    class Level
    {
        public List<LevelPlatformsContainer> level_platforms_container = new List<LevelPlatformsContainer>();
        private Texture2D background;
       // private List<Mechanism> mechanisms = new List<Mechanism>();
        private bool level_complete = false;
        private Vector2 level_gateway_position;
        //private Animation level_gateway;
       // Mechanism tmp_mech = null;
        private string level_name;
        Stage tmp_stage = null;
        private List<Stage> stages = new List<Stage>();
        public SpriteBatch sb;

        public static int current_mech=0;

        private Level1And3 lvl1A3 = new Level1And3();
        public int levelState = 1; //<========================nehany helyen valtoztatva van, de ha te nem hasznalsz hasonlot szerintem nem fogja zavarni a te kododat, a csapdakra 
        // meg egyket kirajzolasra hat (3 nal nagyobb erten mar nincs takarva a palya)
        private float statePercent = 0;  //  <<===================== szinten a csapdakra meg a kirajzolasokra hat
        private List<int> platformState = new List<int>();
        private List<Mechanism> mechanisms = new List<Mechanism>();
        private Animation level_gateway;
        Mechanism tmp_mech = null;
        private Player player;

        public Level(string background_name, SpriteBatch _sb,Player _player)
        {   

            player=_player;
            sb = _sb;

            level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(80, 325), "lvl1/trap", true)); ////////////////////////
           // level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(180, 325), "lvl1/trap", true));
            level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(280, 325), "lvl1/trap", true));
           // level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(380, 325), "lvl1/trap", true));//  a csapdak csak copy paste
            level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(480, 325), "lvl1/trap", true));
            
            level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(580, 350), "lvl1/trap", true));
            level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(680, 350), "lvl1/trap", true));
           // level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(680, 350), "lvl1/trap", true)); ////////////////////////

            //  roof
            level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(0, -20), "ground", false));                  
            //  top
            level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(80, 100), "platform2", false));      
            //  second
            level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(0, 220), "platform2", false));          
            //  third
            level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(80, 340), "platform2", false));
            //  floor            
            level_platforms_container.Add(new LevelPlatformsContainer(new Vector2(0, 460), "ground", false));          

            InitMechs(sb);

            level_gateway_position = new Vector2(780, 330);
            level_gateway = new Animation(ContentLoader.LoadTexture("level_getway"), 1, 1, 1);

            background = ContentLoader.LoadTexture(background_name);

            level_name = background_name;

            platformState.Add(1); //<=====================
            platformState.Add(2); //<===================== a csapdak mozgatasahoz
            platformState.Add(3); //<=====================
        }

        public void InitMech1(SpriteBatch sb)
        {   

            Mechanism mech = new Mechanism(new Vector2(400f, 75f), sb, ContentLoader.LoadTexture("start_machine_button"), ContentLoader.LoadTexture("mechanism_box"), ContentLoader.LoadTexture("mechanism_background"), ContentLoader.LoadTexture("objective1"));
            GearWheel gw = new GearWheel(new Vector2(250, 400), 40, 0.0f, ContentLoader.LoadTexture("gearWheel400"), ContentLoader.LoadTexture("tooth2"), ContentLoader.LoadTexture("smallNumbers/num1"));

            Axis ax = new Axis(new Vector2(550, 250), ContentLoader.LoadTexture("axis1"));

            mech.AddWheel(new GearWheel(new Vector2(300, 400), 40, 0.0f, ContentLoader.LoadTexture("gearWheel400"), ContentLoader.LoadTexture("tooth2"), ContentLoader.LoadTexture("smallNumbers/num1")));
            mech.AddWheel(new GearWheel(new Vector2(300, 400), 20, 0.0f, ContentLoader.LoadTexture("gearWheel400"), ContentLoader.LoadTexture("tooth2"), ContentLoader.LoadTexture("smallNumbers/num2")));
            mech.AddWheel(new GearWheel(new Vector2(300, 400), 8, 0.0f, ContentLoader.LoadTexture("gearWheel400"), ContentLoader.LoadTexture("tooth2"), ContentLoader.LoadTexture("smallNumbers/num5")));
            mech.AddWheel(new GearWheel(new Vector2(300, 400), 5, 0.0f, ContentLoader.LoadTexture("gearWheel400"), ContentLoader.LoadTexture("tooth2"), ContentLoader.LoadTexture("smallNumbers/num8")));
            mech.AddWheel(gw);

            mech.AddAxis(ax);
            mech.AddAxis(new Axis(new Vector2(240, 250), ContentLoader.LoadTexture("axis1")));

            //gw.HandDrived = true;
            gw.IsFixed = true; // the player cant able to change this wheel (need only if not hand drived)
            gw.GearWheelPostion = ax.Position;
            gw.Axis = ax;

            ax.Driver = true;
            ax.RotateSpeed = 0.04f;
            ax.Gear = gw;

            mech.Input = 3; // how many times (need only if not hand drived)
            mech.ExpectedOutput = 15;
            mech.OrganizeSelector(); // sort the unselected wheels

            if (mechanisms.Count > 0)
            {
                mechanisms[0] = mech;
            }
            else
            {
                mechanisms.Add(mech);
            }
            //mech.Active = true;
            // hand drived example
            /*==============================================
             * gw.handDrived = true;
             * gw.GearWheelPosition = ax.Position;
             * gw.Axis = ax;
             * 
             * ax.Gear = gw;
             * 
             * mech.Active = true;
            *==============================================*/
        }

        public void InitMech2(SpriteBatch sb)
        {
            Mechanism mech2 = new Mechanism(new Vector2(600f, 320f), sb, ContentLoader.LoadTexture("start_machine_button"), ContentLoader.LoadTexture("mechanism_box"), ContentLoader.LoadTexture("mechanism_background"), ContentLoader.LoadTexture("objective3"));
            GearWheel gw2 = new GearWheel(new Vector2(200, 400), 50, 0.0f, ContentLoader.LoadTexture("gearWheel400hand"), ContentLoader.LoadTexture("tooth2"), ContentLoader.LoadTexture("smallNumbers/num1"));
            GearWheel gw3 = new GearWheel(new Vector2(200, 400), 25, 0.0f, ContentLoader.LoadTexture("gearWheel400"), ContentLoader.LoadTexture("tooth2"), ContentLoader.LoadTexture("smallNumbers/num1"));

            Axis ax2 = new Axis(new Vector2(505, 250), ContentLoader.LoadTexture("axis1"));
            Axis ax3 = new Axis(new Vector2(210, 250), ContentLoader.LoadTexture("axis1"));

            mech2.AddWheel(gw3);
            mech2.AddWheel(gw2);

            mech2.AddAxis(ax2);
            mech2.AddAxis(ax3);

            gw2.HandDrived = true;
            //gw2.IsFixed = true; // the player cant able to change this wheel (need only if not hand drived)
            gw2.GearWheelPostion = ax2.Position;
            gw2.Axis = ax2;
            gw2.SetTeethToAngle(-1 * (float)(Math.PI / 2));

            gw3.GearWheelPostion = ax3.Position;
            gw3.Axis = ax3;
            gw3.IsFixed = true;

            ax2.Gear = gw2;
            ax3.Gear = gw3;


            mech2.Active = true;

            mech2.ExpectedOutput = 8;

            mech2.SyncWheels(gw2, gw3);

            if (mechanisms.Count>1)
            {
                mechanisms[1] = mech2;
            }
            else
            {
                mechanisms.Add(mech2);
            }
        }

        private void InitMechs(SpriteBatch sb)
        {

            stages.Add(new Stage(0, sb));
            stages.Add(new Stage(1, sb));

            InitMech1(sb);
            InitMech2(sb);
            
        }

        public void Update(GameTime game_time)
        {

            foreach (LevelPlatformsContainer _level_platforms in level_platforms_container)
            {
                _level_platforms.Update();
            }
                foreach (Stage _stage in stages)
                {
                    _stage.UpdateStage();
                    CheckLevelComplete();
                }


                foreach (Mechanism _mechanism in mechanisms)
                {
                    _mechanism.Update();
                    CheckLevelComplete();
                }
                foreach (LevelPlatformsContainer _level_platforms in level_platforms_container)
                {
                    _level_platforms.Update();
                }
                if (levelState >= 5)
                {
                    MoveTraps(); // ha meg lett oldva a harmadik feladvany 
                }

                level_gateway.Animating();
                //  nem a legjobb modszer de mukodik  osszehangolja a Level1And3 es a Level osztaly levelState valtozojat
                if (lvl1A3.levelState > levelState)
                    levelState = lvl1A3.levelState;
                lvl1A3.levelState = levelState;
        }

        public void CheckStageCorrection(Player player)
        {
            for(int i=0;i<stages.Count;i++)
            {
                if (stages[i].StageReset == true)
                {
                    player.PlayerPosition = new Vector2(30, stages[i].Mechanism.Position.Y - player.PlayerAnimation.SpriteHeight);
                    stages[i] = new Stage(stages[i].StageNumber, sb);
                    player.CollisionWithMechanism = false;
                    Player.PlayerActivity = true;
                    stages[i].PlayerPosition = player.PlayerPosition;
                    break;
                }
                else
                {
                    stages[i].PlayerPosition = player.PlayerPosition;
                }
            }
        }

        private void CheckLevelComplete()
        {
            bool complete = true;

            foreach (Stage _stage in stages)
            {
                if (_stage.Mechanism.Done == false || _stage.Mechanism.Solved==false)
                {
                    complete = false;
                    break;
                }   
            }
            level_complete = complete;

            if (mechanisms[0].Done && levelState == 1)
            {
                if (mechanisms[0].Solved)
                {
                    levelState = 2; // felfedi a palya tobbi reszet
                }
                else
                {
                    Player.PlayerActivity = true;
                    Player.PlayerLive = false;
                    current_mech = 0;
                    Game1.mySoundEffects.Play("death");
                }

            }
            if (mechanisms[1].Done && levelState == 4)
            {
                if (mechanisms[1].Solved)
                {
                    levelState = 5; //aktivalja a csapdak mozgasat(kurva ovatosan kell atkelni rajta(az ugras szarra se jo))
                }
                else  // a csapdak agyonbasznak ha elcseszed a feladatot nem tul latvanyos , de mukodik
                {
                    
                    
                         //   MoveLeftTraps();
                            current_mech = 1;

                    
                }
            }
            if (mechanisms[1].Done == true && mechanisms[1].Solved == false)
            {
                MoveLeftTraps();
            }
            //<=============================================================================================
            //  csereld ki amire gondolod
            if (levelState == 6)
                complete = true;
            level_complete = complete;
        }

        private void MoveTraps()
        {
            for (int i = 0; i < 3; i++)
            {
                if ((platformState[1] + i) % 3 == 0)
                {
                    level_platforms_container[i].ItemPosition = new Vector2(level_platforms_container[i].ItemPosition.X, ((1 - statePercent) * 350 + statePercent * 325));
                }
                else if ((platformState[0] + i) % 3 == 0)
                {
                    level_platforms_container[i].ItemPosition = new Vector2(level_platforms_container[i].ItemPosition.X, ((1 - statePercent) * 325 + statePercent * 350));
                }
            }
            statePercent += 0.007f;
            if (statePercent >= 1)
            {
                statePercent = 0;
                platformState[0]++;
                platformState[1]++;
                platformState[2]++;
            }
        }
        private void MoveLeftTraps()
        {
            for (int i = 3; i < 5; i++)
            {
                if ((platformState[1] + i) % 3 == 0)
                {
                    level_platforms_container[i].ItemPosition = new Vector2(level_platforms_container[i].ItemPosition.X, ((1 - statePercent) * 350 + statePercent * 325));
                }
                else if ((platformState[0] + i) % 3 == 0)
                {
                    level_platforms_container[i].ItemPosition = new Vector2(level_platforms_container[i].ItemPosition.X, ((1 - statePercent) * 325 + statePercent * 350));
                }
            }
            statePercent += 0.007f;
            if (statePercent >= 1)
            {
                statePercent = 0;
                platformState[0]++;
                platformState[1]++;
                platformState[2]++;
            }
        }

        public void DrawLevel(SpriteBatch sprite_batch)
        {
            sprite_batch.Draw(background, new Vector2(0, 0), Color.White);

            foreach (LevelPlatformsContainer _item in level_platforms_container)
            {
                _item.DrawLevelItem(sprite_batch);
            }

          

            //<=====================================================================
            lvl1A3.DrawTorches(sprite_batch);  // kirajzolja a faklyakat. Ha kicsereled ne rakd a kirajzolast a vegere mert akkor mindig latszananak a faklyak 
            lvl1A3.DrawPrimLights(sprite_batch); // a fenyeket rajzolja ki amik mindig lathatoak (majdnem mindegy hova lesz rakva)

        

            foreach (Mechanism _mechanism in mechanisms)
            {
                if (_mechanism.DeviceState == 0 || _mechanism.DeviceState == 4)
                {
                    _mechanism.Draw();
                }
                else
                {
                    tmp_mech = _mechanism;
                }
            }
            foreach (Stage _stage in stages)
            {
                if (_stage.Mechanism.DeviceState == 0 || _stage.Mechanism.DeviceState == 4)
                {
                    _stage.DrawStage(sprite_batch);
                }
                else
                {
                    tmp_stage = _stage;
                }
            }
            if (tmp_stage != null)
            {
                tmp_stage.DrawStage(sprite_batch);
                tmp_stage = null;
            }

            //  a sotetitoket rajzolja ki (minel kesobb hivodik meg annal jobb)<===========================================
            if (levelState == 1 || levelState == 2 || levelState == 3)
                lvl1A3.DrawShaders(sprite_batch);

            if (tmp_mech != null)
            {
                tmp_mech.Draw();
                tmp_mech = null;
            }

    
        }

        public List<Stage> LevelStages
        {
            get
            {
                return stages;
            }
        }

        public List<LevelPlatformsContainer> LevelPlatforms
        {
            get
            {
                return level_platforms_container;
            }
        }

        public List<Mechanism> LevelMechanisms
        {
            get
            {
                return mechanisms;
            }
        }

        public bool LevelComplete
        {
            get
            {
                return level_complete;
            }
        }

        public string LevelName
        {
            get
            {
                return level_name;
            }
        }

        public bool CheckPlayerIsGateway(Player player)
        {
            Rectangle player_rectangle = new Rectangle((int)player.PlayerPosition.X, (int)player.PlayerPosition.Y, player.PlayerAnimation.SpriteWidth, player.PlayerAnimation.SpriteHeight);
            Rectangle gateway_rectangle = new Rectangle((int)level_gateway_position.X, (int)level_gateway_position.Y, 100, 150);

            if (player_rectangle.Intersects(gateway_rectangle))
            {
                return true;
            }
            return false;
        }
    }

    class LevelPlatformsContainer
    {
        private Vector2 item_position = new Vector2();
        private Vector2 item_original_position;
        private Texture2D item_texture;
        public static bool go_to_second_position = false;
        public static int PLATFORM_MOVE_SPEED = 3;
        private bool trap = false;

        public void Update()
        {

        }

        public LevelPlatformsContainer(Vector2 _item_position, string item_name, bool _trap)
        {
            item_original_position = _item_position;
            item_position = _item_position;
            item_texture = ContentLoader.LoadTexture(item_name);
            trap = _trap;
        }
        public void DrawLevelItem(SpriteBatch sprite_batch)
        {
            sprite_batch.Draw(item_texture, item_position, Color.White);
        }

        public Texture2D ItemTexture
        {
            get
            {
                return item_texture;
            }
        }
        public Vector2 ItemPosition
        {
            get
            {
                return item_position;
            }
            set
            {
                item_position = value;
            }
        }
        public bool Trap
        {
            get
            {
                return trap;
            }
        }
    }
}
